package cn.com.chengmandian.bike.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.com.chengmandian.bike.constants.BikeConstants;
import cn.com.chengmandian.bike.dto.IdentityAuthAuditForm;
import cn.com.chengmandian.bike.dto.IdentityAuthDto;
import cn.com.chengmandian.bike.dto.IdentityAuthForm;
import cn.com.chengmandian.bike.dto.IdentityMemberStudentForm;
import cn.com.chengmandian.bike.model.EbIdentityAuth;
import cn.com.chengmandian.bike.mapper.EbIdentityAuthMapper;
import cn.com.chengmandian.bike.model.EbIdentityInfo;
import cn.com.chengmandian.bike.model.EbMemberInfo;
import cn.com.chengmandian.bike.model.vo.IdentityAuthVo;
import cn.com.chengmandian.bike.service.IEbIdentityAuthService;
import cn.com.chengmandian.bike.service.IEbIdentityInfoService;
import cn.com.chengmandian.bike.service.IEbMemberInfoService;
import cn.com.chengmandian.bike.utils.WxMiniService;
import cn.com.chengmandian.bike.utils.WxPayUtil;
import cn.com.chengmandian.core.common.constants.CommonConstant;
import cn.com.chengmandian.core.common.utils.HttpUtils;
import cn.com.chengmandian.core.redis.service.RedisService;
import cn.com.chengmandian.core.web.exceptions.BadResponseException;
import cn.com.chengmandian.core.web.pojo.AgentInfo;
import cn.com.chengmandian.service.bike.BikeCommonClient;
import cn.com.chengmandian.service.bike.constants.*;
import cn.com.chengmandian.service.bike.form.MessageAddForm;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 电单车运营-身份认证审核 服务实现类
 * </p>
 *
 * @author AutoGenerator
 * @since 2024-09-18
 */
@Slf4j
@Service
public class EbIdentityAuthServiceImpl extends ServiceImpl<EbIdentityAuthMapper, EbIdentityAuth> implements IEbIdentityAuthService {

    @Autowired
    private IEbIdentityInfoService identityInfoService;
    @Autowired
    private WxMiniService wxMiniService;
    @Autowired
    private IEbMemberInfoService memberInfoService;
    @Autowired
    private BikeCommonClient commonClient;
    @Autowired
    private RedisService redisService;

    @Override
    public void memberAuth(Integer memberId, List<Integer> identityInfoIds) {
        EbIdentityAuth identityAuth = this.getOne(new LambdaQueryWrapper<EbIdentityAuth>()
                .in(EbIdentityAuth::getIdentityId, identityInfoIds)
                .eq(EbIdentityAuth::getMemberId, memberId)
                .eq(EbIdentityAuth::getAuthStatus, IdentityAuthStatusEnum.PASS.getCode())
                .last("limit 0,1"));
        if(identityAuth == null) {
            throw new BadResponseException(523, "身份信息不满足此次购买，请您先去完善身份认证信息");
        }
    }

    @Override
    public EbIdentityAuth newestAuth(Integer identityId, Integer memberId) {
        return this.getOne(new LambdaQueryWrapper<EbIdentityAuth>()
                .in(EbIdentityAuth::getIdentityId, identityId)
                .eq(EbIdentityAuth::getMemberId, memberId)
                .orderByDesc(EbIdentityAuth::getId)
                .last("limit 0,1"));
    }

    @Override
    public IPage<IdentityAuthVo> getPage(IdentityAuthDto dto, Integer memberId) {
        Page page = Page.of(dto.getPageNumber(), dto.getPageSize());
        return baseMapper.getPage(page, dto, memberId);
    }

    @Override
    public EbIdentityAuth addAuth(IdentityAuthForm form, Integer memberId) {
        String redisLockKey = BikeConstants.REDIS_LOCK_MEMBER_IDENTITY_AUTH.concat(memberId + ":" + form.getIdentityId());
        Assert.isTrue(redisService.setNx(redisLockKey, form.getIdentityId(), 3), "请您不要重复认证");

        EbIdentityInfo identityInfo = identityInfoService.getById(form.getIdentityId());
        Assert.notNull(identityInfo, "验证类型方式不存在");

        if(this.count(new LambdaQueryWrapper<EbIdentityAuth>()
                .eq(EbIdentityAuth::getIdentityId, identityInfo.getId())
                .in(EbIdentityAuth::getAuthStatus, IdentityAuthStatusEnum.WAIT.getCode(), IdentityAuthStatusEnum.PASS.getCode())
                .eq(EbIdentityAuth::getMemberId, memberId)) > 0) {
            throw new BadResponseException("该身份已在审核中或认证通过，请您不要重复认证！");
        }

        EbIdentityAuth identityAuth = new EbIdentityAuth();
        identityAuth.setIdentityId(identityInfo.getId());
        identityAuth.setMemberId(memberId);
        identityAuth.setName(form.getName());
        identityAuth.setCardName(identityInfo.getCardName());
        identityAuth.setCardNo(form.getCardNo());
        identityAuth.setSubmitTime(DateUtil.date());

        IdentityAuthTypeEnum authTypeEnum = IdentityAuthTypeEnum.PERSON;
        if(identityInfo.getIsThirdAuth().equals(CommonConstant.ONE)) {
            authTypeEnum = IdentityAuthTypeEnum.THIRD;
        }
        IdentityAuthStatusEnum authStatusEnum = IdentityAuthStatusEnum.WAIT;
        if(identityInfo.getIsAutoPass().equals(CommonConstant.ONE)) {
            authStatusEnum = IdentityAuthStatusEnum.PASS;
            authTypeEnum = IdentityAuthTypeEnum.AUTO;
            identityAuth.setAuthRemark("自动审核通过");
            identityAuth.setAuthTime(DateUtil.date());
            identityAuth.setAuthUser(0);
            identityAuth.setAuthName("系统");
        }
        identityAuth.setAuthType(authTypeEnum.getCode());
        identityAuth.setAuthStatus(authStatusEnum.getCode());
        this.save(identityAuth);
        return identityAuth;
    }

    @Override
    public Map memberStudent(IdentityMemberStudentForm form, Integer memberId, AgentInfo agentInfo) {
        EbMemberInfo memberInfo = memberInfoService.getById(memberId);
        Assert.isTrue(StrUtil.isNotBlank(memberInfo.getOpenId()), "缺少用户OPEN_ID");

        EbIdentityAuth identityAuth = this.getById(form.getIdentityAuthId());
        Assert.notNull(identityAuth, "缺少身份认证信息");
        WxMaService wxMaService = wxMiniService.getMaServices();
        String accessToken = "";
        try{
            accessToken = wxMaService.getAccessToken();
        }catch (Exception ex) {
            log.error("access token获取异常:{}", ex.getMessage());
            throw new BadResponseException("系统繁忙,请稍后再试");
        }
        Assert.isTrue(StrUtil.isNotBlank(accessToken), "未获取到access_token");

        Map<String, String> queryMap = new HashMap<>();
        queryMap.put("access_token", accessToken);

        Map<String, String> bodyMap = new HashMap<>();
        bodyMap.put("openid", memberInfo.getOpenId());
        bodyMap.put("wx_studentcheck_code", form.getWxStudentcheckCode());

        try {
            HttpResponse response = HttpUtils.doPost("https://api.weixin.qq.com", "/intp/quickcheckstudentidentity",  null, new HashMap<>(), queryMap, bodyMap);
            Map<String, String> responseMap = JSONObject.parseObject(EntityUtils.toString(response.getEntity()), Map.class);
            Boolean isStudent = MapUtil.getBool(responseMap, "is_student", false);
            Integer errcode = MapUtil.getInt(responseMap, "errcode", 0);
            String remark = "";
            if(!isStudent || !errcode.equals(CommonConstant.ZERO)) {
                this.update(new LambdaUpdateWrapper<EbIdentityAuth>()
                        .set(EbIdentityAuth::getAuthStatus, IdentityAuthStatusEnum.FAIL.getCode())
                        .set(EbIdentityAuth::getAuthUser, 0)
                        .set(EbIdentityAuth::getAuthName, "系统")
                        .set(EbIdentityAuth::getAuthRemark, MapUtil.getStr(responseMap, "errmsg", "").concat(" errcode: ").concat(errcode.toString()))
                        .set(EbIdentityAuth::getAuthTime, DateUtil.date())
                        .eq(EbIdentityAuth::getId, form.getIdentityAuthId()));
                remark = "【" + identityAuth.getCardName() +"】认证未通过，请重新提交认证信息";
            }else {
                this.update(new LambdaUpdateWrapper<EbIdentityAuth>()
                        .set(EbIdentityAuth::getAuthStatus, IdentityAuthStatusEnum.PASS.getCode())
                        .set(EbIdentityAuth::getAuthUser, 0)
                        .set(EbIdentityAuth::getAuthName, "系统")
                        .set(EbIdentityAuth::getAuthRemark, "学生认证通过")
                        .set(EbIdentityAuth::getAuthTime, DateUtil.date())
                        .eq(EbIdentityAuth::getId, form.getIdentityAuthId()));
                remark = "【" + identityAuth.getCardName() +"】身份认证已通过";
            }

            // 发送系统消息
            MessageAddForm messageAddForm = new MessageAddForm();
            messageAddForm.setMemberId(memberInfo.getId());
            messageAddForm.setChannel(MessageChannelEnum.SYS);
            messageAddForm.setContent(remark);
            messageAddForm.setBusinessId(form.getIdentityAuthId());
            messageAddForm.setBusinessType(MessageBusinessTypeEnum.IDENTITY_AUTH);
            messageAddForm.setImage(null);
            messageAddForm.setPushChannel(PushChannelEnum.MEMBER_MESSAGE.getCode());
            messageAddForm.setBusinessCategory(MessageBusinessCategoryEnum.RIDE_IDENTITY_AUTH.getCode());
            commonClient.sendMessage(agentInfo.getId(), messageAddForm);
            return responseMap;
        } catch (Exception ex) {
            log.error("获取学生信息异常:{}", ex.getMessage());
            throw new BadResponseException("获取学生信息失败");
        }
    }

    @Override
    public void audit(IdentityAuthAuditForm form) {
        EbIdentityAuth identityAuth = this.getById(form.getId());
        Assert.notNull(identityAuth, "审核信息不存在");

        String redisLockKey = BikeConstants.REDIS_LOCK_MEMBER_IDENTITY_AUTH.concat(identityAuth.getMemberId() + ":" + identityAuth.getIdentityId());
        Assert.isTrue(redisService.setNx(redisLockKey, form.getIdentityId(), 3), "请您不要重复提交认证");

        Assert.isTrue(!IdentityAuthStatusEnum.PASS.getCode().equals(identityAuth.getAuthStatus())
                && !IdentityAuthStatusEnum.FORBID.getCode().equals(identityAuth.getAuthStatus()), "不支持再次提交");

        this.update(new LambdaUpdateWrapper<EbIdentityAuth>()
                .set(EbIdentityAuth::getAuthStatus, IdentityAuthStatusEnum.WAIT.getCode())
                .set(EbIdentityAuth::getSubmitTime, DateUtil.date())
                .set(EbIdentityAuth::getIdentityId, form.getIdentityId())
                .set(EbIdentityAuth::getName, form.getName())
                .set(EbIdentityAuth::getCardNo, form.getCardNo())
                .eq(EbIdentityAuth::getId, identityAuth.getId()));
    }
}
